package controllers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jj.play.org.eclipse.mylyn.wikitext.core.parser.builder.HtmlDocumentBuilder;
import net.sf.ehcache.search.Query;
import net.sf.ehcache.search.Results;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.validator.util.privilegedactions.GetClassLoader;
import org.objectweb.asm.TypeReference;
import org.tempuri.InJsonData;
import org.tempuri.ReturnResult;
import org.tempuri.WebServiceHelpUtil;
import org.tempuri.CoordinateServiceStub.GetJsonData;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ning.http.client.Request;
import com.sun.corba.se.impl.protocol.giopmsgheaders.Message;

import config.AppConfig;
import config.AppConfig;
import config.SessionConfig;
import models.CountingRoom;
import models.HtmlReqException;
import models.JSONReqException;
import models.Menu;
import models.Result;
import models.ReturnData;
import models.User;
import play.Logger;
import play.Play;
import play.cache.Cache;
import play.data.validation.Required;
import play.libs.Codec;
import play.libs.Images;
import play.mvc.Before;
import play.mvc.Catch;
import play.mvc.Controller;
import play.mvc.Router;
import play.mvc.Router.Route;

public class BaseController extends Controller {
	@Before(unless={"login", "logout", "doLogin", "captcha", "checkLogin", "browerNotSupport"}, priority=1)
	public static void before() throws HtmlReqException{
		String ctxPath = Play.ctxPath;
		renderArgs.put("ctxPath", ctxPath==null?"":ctxPath);
		User user = new User();
		user.setUsercode("admin");
		user.setUsername("管理员");
		/*if(user==null){
			if("html".equals(request.format)){
				login();
				return;
			}else if("txt".equals(request.format)){
				Result result = new Result();
				result.setCode(AppConfig.NO_LOGIN);
				renderJSON(result);
				return;
			}
		}*/
		setLoginUser(user);
		if(user!=null){
			Result result = (Result) Cache.get(user.getUsercode()+"_"+session.getId());
			Cache.set(user.getUsercode()+"_"+session.getId(), result, "30mn");
		}
	}
	
	public static void checkLogin(){
		Result result = new Result();
		result.setCode(AppConfig.SUCCESS);
		renderJSON(result);
	}
	
	@Before(unless={"login", "logout", "doLogin", "captcha"}, priority=2)
	public static void setUsername(){
		User user = getLoginUser();
		if(user!=null){
			renderArgs.put("username", user.getUsername());
		}
	}
	
	public static void login(){
		try {
			ReturnResult returnResult= WebServiceHelpUtil.execute(InJsonData.getRequsetJsonData("0", AppConfig.PLAT_GETCOUNTINGROOMNAME, "", AppConfig.CURRENT_PLAT, "", request.remoteAddress, ""));
			if(returnResult.isSuccess()){
				ReturnData<CountingRoom> retData = JSON.parseObject(returnResult.getJsonStr(), new ReturnData<CountingRoom>().getClass());
				List<CountingRoom> countingRooms = retData.getReturnTable();
				renderArgs.put("countingRooms", countingRooms);
				if(countingRooms==null||countingRooms.size()==0){
					renderArgs.put("canLogin", false);
				}else{
					renderArgs.put("canLogin", true);
				}
			}
		} catch (Exception e) {
			throw new HtmlReqException(e.getMessage());
		}
		String codeId = Codec.UUID();
		renderArgs.put("codeId", codeId);
		render();
	}
	
	/**
	 * 登录
	 * @param username
	 * @param password
	 * @param countingRoomName 账套名称(数据库名)
	 * @param validCode 验证码
	 * @param codeId 验证存储key值
	 */
	public static void doLogin(String username, String password, String countingRoomName, String validCode, String codeId){
		Result result = new Result();
		if(!canLogin()){
			result.setCode(AppConfig.ERROR);
			result.setData(SessionConfig.WARN_MESSAGE);
			renderJSON(result);
		}
		if(StringUtils.isEmpty(username)){
			result.setCode(AppConfig.ERROR);
			result.setData("用户名不能为空");
			renderJSON(result);
		}
		if(StringUtils.isEmpty(password)){
			result.setCode(AppConfig.ERROR);
			result.setData("密码不能为空");
			renderJSON(result);
		}
		if(StringUtils.isEmpty(validCode)){
			result.setCode(AppConfig.ERROR);
			result.setData("验证码不能为空");
			renderJSON(result);
		}
		if(StringUtils.isEmpty(codeId)){
			result.setCode(AppConfig.ERROR);
			result.setData("验证码ID不能为空");
			renderJSON(result);
		}
		if(StringUtils.isEmpty(countingRoomName)){
			result.setCode(AppConfig.ERROR);
			result.setData("账套不能为空");
			renderJSON(result);
		}
		String myCode = (String) Cache.get(codeId);
		if(myCode==null){
			result.setCode(AppConfig.ERROR);
			result.setData("验证码已过期，请刷新验证码");;
			renderJSON(result);
		}
		if(!validCode.toUpperCase().equals(myCode.toUpperCase())){
			result.setCode(AppConfig.ERROR);
			result.setData("验证码错误");
			renderJSON(result);
		}
		try {
			JSONObject queryJson = new JSONObject();
			queryJson.put("UserCode", username);
			queryJson.put("Password", password);
			List<JSONObject> jsonList = new ArrayList<JSONObject>();
			jsonList.add(queryJson);
			Map<String, List<JSONObject>> dataSet= new HashMap<String, List<JSONObject>>();
			dataSet.put("InfoTable", jsonList);
			String jsonStr = InJsonData.getRequsetJsonData("0", AppConfig.PLAT_LOGIN, username, AppConfig.CURRENT_PLAT , countingRoomName, request.remoteAddress, "", dataSet);
			ReturnResult retResult = WebServiceHelpUtil.execute(jsonStr);
			JSONObject retJson = JSONObject.parseObject(retResult.getJsonStr());
			if(retResult.isSuccess()){
				JSONArray array = retJson.getJSONArray("ReturnTable");
				if(array.size()!=1){
					result.setCode(AppConfig.ERROR);
					result.setData("用户名或密码确认，请重新输入");
					renderJSON(result);
				}
				User user = new User();
				user.setUsercode(((JSONObject)array.get(0)).getString("UserCode"));
				user.setUsername(((JSONObject)array.get(0)).getString("UserName"));
				user.setDbName(countingRoomName);
				setLoginUser(user);
				result.setCode(AppConfig.SUCCESS);
				renderJSON(result);
			}else{
				JSONArray array = retJson.getJSONArray("CommonReturnInfoTable");
				result.setCode(AppConfig.ERROR);
				result.setData(((JSONObject)array.get(0)).getString("ExcpetionData"));
				renderJSON(result);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			throw new JSONReqException(e.getMessage());
		}
	}
	
	/**
	 * 登出
	 */
	public static void logout(){
		releaseSession();
		login();
	}
	
	/**
	 * 释放session资源
	 */
	private static void releaseSession(){
		User user = getLoginUser();
		Cache.safeDelete(SessionConfig.SESSION_PREFIX + session.getId());
		Cache.safeDelete(user.getUsercode() + "_" + session.getId());
		session.clear();
	}
	
	/**
	 * 图形验证码
	 * @param codeId 
	 */
	public static void captcha(String codeId) {
	    Images.Captcha captcha = Images.captcha();
	    String code = captcha.getText("#49B07F",4);
	    Cache.set(codeId, code, "30mn");
	    renderBinary(captcha);
	}
	
	/**
	 * 拦截json请求异常
	 * @param throwable
	 */
	@Catch(value=JSONReqException.class)
	public static void handleJSONReqException(Throwable throwable){
		Logger.error(throwable.getMessage());
		Result result = new Result();
		result.setCode(AppConfig.ERROR);
		result.setMessage("程序发生异常请稍后再试");
		renderJSON(result);
	}
	
	/**
	 * 拦截html请求异常
	 * @param throwable 
	 */
	@Catch(value=HtmlReqException.class)
	public static void hanlderHtmlReqException(Throwable throwable){
		Logger.error(throwable.getMessage());
		notFound();
	}
	
	/**
	 * 拼装请求参数
	 * @param handleCode
	 * @param functionId
	 * @param otherTables
	 * @return 请求参数
	 */
	protected static String getInJsonStr(String handleCode, String functionId, Map<String, List<JSONObject>> otherTables){
		User user = getLoginUser();
		return InJsonData.getRequsetJsonData("0", handleCode, user.getUsercode(), AppConfig.CURRENT_PLAT, user.getDbName(), request.remoteAddress, "", otherTables);
	}
	
	/**
	 * 检测权限
	 * @return
	 */
	public static boolean checkPermission(String functionId){
		User user = getLoginUser();
		if(StringUtils.isEmpty(functionId)){
			return false;
		}
		Map<String, List<JSONObject>> otherTables = new HashMap<String, List<JSONObject>>();
		JSONObject json = new JSONObject();
		json.put("FunctionID", functionId);
		json.put("UserCode", user.getUsercode());
		List<JSONObject> infoTable = new ArrayList<JSONObject>();
		infoTable.add(json);
		otherTables.put("InfoTable", infoTable);
		String jsonStr = getInJsonStr(AppConfig.PLAT_SECURITYCHECK, "", otherTables);
		try {
			ReturnResult result = WebServiceHelpUtil.execute(jsonStr);
			if(result.isSuccess()){
				return true;
			}
			return false;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			Logger.error(e.getMessage());
			return false;
		}
	}
	
	/**
	 *  做数据检查的辅助类
	 * @author Administrator
	 *
	 */
	protected static class CheckResult{
		
		public CheckResult(boolean result, String msg) {
			super();
			this.result = result;
			this.msg = msg;
		}
		public boolean result;
		public String msg;
	}
	
	public static void report(){
		render();
	}
	
	public static void browerNotSupport(){
		renderTemplate("errors/browserNotSupport.html");
	}
	
	/**
	 * 判断当前是否超出session数量限制
	 * @return
	 */
	private static boolean canLogin(){
		net.sf.ehcache.CacheManager cm = net.sf.ehcache.CacheManager.create();
		net.sf.ehcache.Cache cache = cm.getCache("play");
		try{
			Query q = cache.createQuery();
			q.includeKeys();
			//后续需修改session存入方式
			q.addCriteria(Query.KEY.ilike(SessionConfig.SESSION_PREFIX + "*"));
			Results results = q.execute();
			if(results.size()>=SessionConfig.SESSION_COUNT_LIMIT){
				return false;
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return true;
	}
	
	/**
	 * 得到当前登录的用户信息
	 * @return
	 */
	protected static User getLoginUser(){
		User user = Cache.get(SessionConfig.SESSION_PREFIX + session.getId(), User.class);
		return user;
	}
	
	/**
	 * 设置当前登录的用户
	 * @param user
	 */
	private static void setLoginUser(User user){
		Cache.set(SessionConfig.SESSION_PREFIX + session.getId(), user, "30mn");
	}
}
